/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "S_PhysicsODE.h"

#include <ppl.h>

#include "../../../../../物体/实现包含物体.h"
#include "../B_物理体/ODE刚体.h"

#include "S_键值序列容器.h"



using namespace std;





struct S_ODE : public S_Physics {
	S_ODE核心	m_Core;
	S_键值序列容器<uint32, dBodyID>	m_Body;

	S_ODE() {

	}
	~S_ODE() {

	}




	void	f_Update() {
		//dWorldStep(m_Core.m_物理世界, m_步进时间);
		dWorldQuickStep(m_Core.m_物理世界, m_步进时间);
	}
	//void	f_Update车辆(S_Px车* 车);
	void	f_应用物理变换() {

	}



	void	f_取更新物体(std::vector<std::vector<Mat44f>>& mat, std::vector<std::vector<void*>>& userData) {

	}
	void	f_取更新物体(std::vector<Mat44f>& mat, std::vector<void*>& userData) {
		uint32 num = m_Body.size();
		auto* data = m_Body.data();

		Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
			mat.resize(mat.size() + num);
			userData.resize(userData.size() + num);
			auto* p_use = userData.data();
			auto* p_mat = mat.data();

			const float64* pos = dBodyGetPosition(data[i]);
			const float64* rot = dBodyGetRotation(data[i]);
			//vec3 pos;
			C_Mat44 mat = f_从变换构建矩阵(
				{ float32(pos[0]), float32(pos[1]), float32(pos[2]) }, 
				{ float32(rot[0]), float32(rot[1]), float32(rot[2]) },
				{ 1.0f,1.0f,1.0f }
			);

			p_mat[i] = *((Mat44f*)mat.columns);
			//cout << "pos : x=" << pos.x << " y=" << pos.y << " z=" << pos.z << endl;
		});
	}
	void	f_等待更新结束() {

	}
	//S_物理体*	f_创建物理平面(vec4 location, uint32 key);
	void		f_添加物理体(S_物理体* body, uint32 scenekey) {
		dBodyID b = (dBodyID)body->f_getBody();
		if (m_Body.f_is存在(b) == false) {
			uint32 id = m_Body.f_GenName(0);
			m_Body.f_add(b, id);
		}
	}
	void		f_移除物理体(S_物理体* body, uint32 scenekey) {
		dBodyID b = (dBodyID)body->f_getBody();
		if (m_Body.f_is存在(b)) {
			m_Body.f_remove(m_Body[b]);
		}
	}



	//S_物理体*	f_add刚体(uint32 key);
	//void		f_add车辆(const S_三角Mesh& 车体, const S_车体参数& 车体参数, vector<S_物体*> 车轮, const vector<S_车轮参数>& 车轮参数);


};









//S_物理体* S_PhysX::f_创建物理平面(vec4 location, uint32 key) {
//	return new S_Px平面(m_PxCore.m_Physics, location, key);
	//m_Px场景s[0]->addActor(*plane->m_Plane);
//}

/*void S_PhysX::f_add车辆(const S_三角Mesh& 车体, const S_车体参数& 车体参数, vector<S_物体*> 车轮, const vector<S_车轮参数>& 车轮参数) {
	uint32 车轮数 = 车轮参数.size();

	S_Px车* px车 = new S_Px车(m_PxCore.m_Physics, m_PxCore.m_Cooking, 车体参数, 车轮数);

	S_模型* c车体 = dynamic_cast<S_模型*>(车体);
	px车->m_车体刚体->userData = c车体;

	auto mesh = c车体->f_get网格();
	px车->f_add构建车体(m_PxCore.m_Physics, m_PxCore.m_Cooking, mesh.f_Map顶点(), mesh.f_get顶点数量());

	for (uint32 i = 0; i < 车轮数; ++i) {
		S_Px车轮* px车轮 = new S_Px车轮(m_PxCore.m_Physics, m_PxCore.m_Cooking, 车轮参数[i]);
		//vec3 轮胎局部位置 = c车体->f_get位置();
		px车->f_add构建车轮(px车轮);
		px车轮->m_车轮形状->userData = 车轮[i];
		//px车->m_车轮.push_back(px车轮);
	}

	m_Px场景s[0]->addActor(*px车->m_车体刚体);

}*/

S_Physics* f_创建ODE物理引擎() {
	return new S_ODE();
}






S_物理几何体* f_ODE平面几何体(S_Physics* 解算器, const vec4& v) {
	auto& Core = dynamic_cast<S_ODE*>(解算器)->m_Core;
	return new S_ODE平面几何体(&Core, v);
}


S_物理几何体* f_ODE长方体几何体(S_Physics* 解算器, const vec3& v) {
	auto& Core = dynamic_cast<S_ODE*>(解算器)->m_Core;
	return new S_ODE长方体几何体(&Core, v);
}

S_物理几何体* f_ODE凸壳几何体(S_Physics* 解算器, const S_三角Mesh mesh) {
	auto& Core = dynamic_cast<S_ODE*>(解算器)->m_Core;
	return new S_ODE凸壳几何体(&Core, mesh);
}

S_物理体* f_ODE刚体(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_ODE*>(解算器)->m_Core;
	return new S_ODE刚体(&Core, geom, mat);
}

S_物理体* f_ODE静态(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_ODE*>(解算器)->m_Core;
	return new S_ODE静态(&Core, geom, mat);
}

